package com.easylinkin.linkappapi.danger.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.common.utils.excel.ExcelConstant;
import com.easylinkin.linkappapi.common.utils.excel.ExcelTools;
import com.easylinkin.linkappapi.common.utils.io.OutputStreamUtil;
import com.easylinkin.linkappapi.danger.dao.DangerMapper;
import com.easylinkin.linkappapi.danger.entity.Danger;
import com.easylinkin.linkappapi.danger.entity.DangerType;
import com.easylinkin.linkappapi.danger.entity.vo.DangerTypeNode;
import com.easylinkin.linkappapi.danger.entity.vo.DangerVo;
import com.easylinkin.linkappapi.danger.service.DangerService;
import com.easylinkin.linkappapi.openapi.util.HttpClientUtil;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.sevice.LinkappTenantService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Danger表服务实现类
 *
 * @author CodeGenerator
 * @date 2022/07/21
 */
@Slf4j
@Service("appDangerService")
public class DangerServiceImpl extends ServiceImpl
        <DangerMapper, Danger> implements DangerService {
    @Resource
    private CommonService commonService;
    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;
    @Resource
    private DangerTypeServiceImpl appDangerTypeService;

//    @Override
//    public boolean saveOne(Danger appDanger) {
//        commonService.setCreateAndModifyInfo(appDanger);
//        appDanger.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
//        validParamRequired(appDanger);
//        validRepeat(appDanger);
//        validParamFormat(appDanger);
//        return save(appDanger);
//    }


//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public boolean updateOne(Danger appDanger) {
//        Assert.notNull(appDanger.getId(), "id不能为空");
//        commonService.setModifyInfo(appDanger);
////        appDanger.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
//        validRepeat(appDanger);
//        validParamFormat(appDanger);
//        return updateById(appDanger);
//    }

    @Override
    public IPage<Danger> selectPage(Page page, Danger appDanger) {
        appDanger.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.selectPage(page, appDanger);
    }

    @Override
    public List<Danger> selectList(Danger appDanger) {
        String tenantId = appDanger.getTenantId();
        if (StringUtils.isEmpty(tenantId)) {
            tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        }
        appDanger.setTenantId(tenantId);
        return baseMapper.selectPage(appDanger);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(List<Long> idList) {
        return removeByIds(idList);
    }

    @Override
    public void export(Danger appDanger, HttpServletRequest request, HttpServletResponse
            response) {

        IPage<Danger> page = selectPage(new Page(0, -1), appDanger);
        List<Danger> records = page.getRecords();
        List
                <DangerVo> appDangerVos = new ArrayList<>();
        for (Danger expert : records) {
            appDangerVos.add(new DangerVo(expert));
        }

        String keyValue = "名称:name,租户id:tenantId";
        String title = "Danger导出数据";
        String fileName = title + ".xls";
        try {
            OutputStream outputStream = OutputStreamUtil
                    .getOutputStream(request, response, fileName);
            ExcelTools.exportExcel(outputStream, keyValue, appDangerVos, ExcelConstant.XLS, title);
            response.flushBuffer();
            outputStream.close();
        } catch (IOException e) {
            log.error("excel导出失败", e);
            throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
        } catch (Exception e) {
            log.error("excel导出失败", e);
            throw new RuntimeException("excel导出失败！" + e.getMessage());
        }
    }

    @Override
    public Danger getOneById(Serializable id) {
        return baseMapper.getOneById(id);
    }

    /**
     * 校验重复
     */
    private void validRepeat(Danger appDanger) {
//        QueryWrapper<Danger> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("name", appDanger.getName());
//        queryWrapper.eq("tenant_id", linkappUserContextProducer.getNotNullCurrent().getTenantId());
//        List<Danger> list = baseMapper.selectList(queryWrapper);
//        if (list.size() == 0) {
//            return;
//        }
//        if (list.size() > 1) {
//            throw new BusinessException("名称有重复");
//        }
//        if (ObjectUtils.isEmpty(appDanger.getId())) {
//            throw new BusinessException("名称已存在");
//        }
//        if (!appDanger.getId().equals(list.get(0).getId())) {
//            throw new BusinessException("名称已存在");
//        }

    }


    /**
     * 校验参数必填
     */
    private void validParamRequired(Danger appDanger) {
        Assert.notNull(appDanger, "参数为空");
//        Assert.isTrue(StringUtils.isNotBlank(appDanger.getName()), "名称为空");
    }

    /**
     * 校验参数格式
     */
    private void validParamFormat(Danger appDanger) {
//        Assert.isTrue(appDanger.getName() == null || appDanger.getName().length() <= 50,
//                "名称超长");
    }

    @Override
    public List<DangerTypeNode> selectListWithType(DangerType dangerType) {
        if(dangerType == null){
            dangerType = new DangerType();
        }
        List<DangerTypeNode> list = appDangerTypeService.selectList(dangerType);
        for (DangerTypeNode dangerTypeNode : list) {
            dangerTypeNode.setId(dangerTypeNode.getDangerTypeId());
            //隐患分类
            dangerTypeNode.setNodeType(1);
        }
        Danger paramDanger = dangerType.getDanger();
        if (paramDanger == null) {
            paramDanger = new Danger();
        }
        paramDanger.setTenantId(dangerType.getTenantId());
        List<Danger> l2 = selectList(paramDanger);
        for (Danger danger : l2) {
            //隐患内容
            DangerTypeNode dangerType2 = new DangerTypeNode(Long.valueOf(danger.getId()), danger.getFullId(), danger.getFullName(), danger.getContent(), danger.getCode(), danger.getLevel(),2);
            dangerType2.setParentId(danger.getDangerTypeId());
            dangerType2.setId(Long.valueOf(danger.getId()));
            dangerType2.setTenantId(danger.getTenantId());
            list.add(dangerType2);
        }
        return list;
    }

    @Override
    public List<DangerTypeNode> selectTreeWithType(DangerType dangerType) {
        return DangerTypeServiceImpl.listToTree(selectListWithType(dangerType));
    }

    @Value("${edu.apiUrl}")
    private String url;
    @Resource
    private LinkappTenantService linkappTenantService;

    @Override
    public void synchronizeData(Integer add, Integer cover) {
        // 项目级 刷数据脚本+用到隐患 的其他业务
        // 其他业务表 用的 app_danger 的需要 加租户隔离 tenant_id
        // 项目级 租户隔离

        try {
            String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
            LinkappTenant tenant = linkappTenantService.getOneById(tenantId);
            syncDangerType(add, cover, tenantId, tenant);
            syncDanger(add, cover, tenantId, tenant);
        } catch (Exception e) {
            log.error("同步隐患库报错", e);
        }

    }

    // 同时考虑 full id 和 full name 同步 如果 full id 本地不存在 单 fullname 相同 则忽略
    private void syncDangerType(Integer add, Integer cover, String tenantId, LinkappTenant tenant) {
        HttpPost httpPost = new HttpPost(
//                    "http://172.16.10.190:16005/api" + "/deviceAttributeStatus/getHistoricDataPageFromEs");
                url + "/enterpriseOpenApi/danger/selectAllType");
        //添加请求头
        httpPost.addHeader("Content-Type", "application/json");
        //设置接收形式
        httpPost.setHeader("Accept", "*/*");
        httpPost.setHeader("token", "5a920f536428050edddcce5212f36a97");
        //设置授权
//        httpPost.setHeader("Blade-Auth", "bearer " + getAccessTokenTest());
//        httpPost.setHeader("Authorization", "Basic c2FiZXI6c2FiZXJfc2VjcmV0");
        //创建登录实体
        httpPost.setEntity(new StringEntity(JSONObject.toJSONString(new HashMap<>()), Charset.forName("UTF-8")));
        log.info("BladeGuardApi request:{}", httpPost);
        String str = HttpClientUtil.doPost(httpPost);
        log.info("同步的数据是：{}", str);
        JSONObject jsonObject = JSONObject.parseObject(str);
        JSONArray data = (JSONArray) jsonObject.get("data");

        QueryWrapper<DangerType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tenant_id", tenantId);
        List<DangerType> localList = appDangerTypeService.list(queryWrapper);
        Map<String, List<DangerType>> localFullNameMap = localList.stream().collect(Collectors.groupingBy(DangerType::getFullName));
        Map<String, List<DangerType>> localFullIdMap = localList.stream().collect(Collectors.groupingBy(DangerType::getFullId));

        for (int i = 0; i < data.size(); i++) {
            JSONObject jsonObject1 = (JSONObject) data.get(i);
            String fullName = (String) jsonObject1.get("fullName");

            String fullId = (String) jsonObject1.get("fullId");
            List<DangerType> list = localFullIdMap.get(fullId);
            if (ObjectUtils.isEmpty(list)) {
                // 同步新增
                if (add != null && add.equals(1)) {
                    if (ObjectUtils.isNotEmpty(localFullNameMap.get(fullName))) {
                        log.info("如果本地有存在的 同名称的 则忽略 不新增");
                        continue;
                    }
                    DangerType newDanger = new DangerType();
                    newDanger.setTenantId(tenantId);
                    newDanger.setLevel((Integer) jsonObject1.get("level"));
                    Date date = Calendar.getInstance().getTime();
                    newDanger.setLastPushTime(date);
                    newDanger.setFullName((String) jsonObject1.get("fullName"));
                    newDanger.setName((String) jsonObject1.get("name"));
                    newDanger.setFullId((String) jsonObject1.get("fullId"));
                    if (jsonObject1.get("dangerTypeId") == null) {
                        continue;
                    }
                    newDanger.setDangerTypeId(Long.valueOf(tenant.getProjectId() + jsonObject1.get("dangerTypeId")));
                    Integer parentId = (Integer) jsonObject1.get("parentId");
                    if (parentId != null) {
                        if (parentId.equals(0)) {
                            newDanger.setParentId(0L);
                        } else {
                            newDanger.setParentId(Long.valueOf(tenant.getProjectId() + parentId));
                        }
                    }
                    try {
                        appDangerTypeService.save(newDanger);
                    } catch (Exception e) {
                        log.error("appDangerTypeService.save 同步报错：", e);
                    }
                }
            } else {
                // 同步覆盖
                if (cover != null && cover.equals(1)) {
                    //根据fullId 设置
                    DangerType e0 = list.get(0);
                    if (e0.getLevel().equals(jsonObject1.get("level")) && e0.getFullName().equals(jsonObject1.get("fullName"))
                            && e0.getName().equals(jsonObject1.get("name"))) {
                        log.info("信息相同，不需要同步");
                        continue;
                    }
                    e0.setLevel((Integer) jsonObject1.get("level"));
                    e0.setFullName((String) jsonObject1.get("fullName"));
                    e0.setName((String) jsonObject1.get("name"));
                    e0.setLastPushTime(Calendar.getInstance().getTime());

                    UpdateWrapper<DangerType> updateWrapper = new UpdateWrapper();
                    updateWrapper.eq("tenant_id", tenantId);
                    updateWrapper.eq("full_id", fullId);
                    try {
                        appDangerTypeService.update(e0, updateWrapper);
                    } catch (Exception e) {
                        log.error("appDangerTypeService.update 同步报错：", e);
                    }

                }
            }
        }
    }

    private void syncDanger(Integer add, Integer cover, String tenantId, LinkappTenant tenant) {
        HttpPost httpPost = new HttpPost(
//                    "http://172.16.10.190:16005/api" + "/deviceAttributeStatus/getHistoricDataPageFromEs");
                url + "/enterpriseOpenApi/danger/selectAll");
        //添加请求头
        httpPost.addHeader("Content-Type", "application/json");
        //设置接收形式
        httpPost.setHeader("Accept", "*/*");
        httpPost.setHeader("token", "5a920f536428050edddcce5212f36a97");
        //设置授权
//        httpPost.setHeader("Blade-Auth", "bearer " + getAccessTokenTest());
//        httpPost.setHeader("Authorization", "Basic c2FiZXI6c2FiZXJfc2VjcmV0");
        //创建登录实体
        httpPost.setEntity(new StringEntity(JSONObject.toJSONString(new HashMap<>()), Charset.forName("UTF-8")));
        log.info("BladeGuardApi request:{}", httpPost);
        String str = HttpClientUtil.doPost(httpPost);
        log.info("同步的数据是：{}", str);
        JSONObject jsonObject = JSONObject.parseObject(str);
        JSONArray data = (JSONArray) jsonObject.get("data");

        List<Danger> local = selectList(new Danger());
        Map<String, List<Danger>> localFullNameMap = local.stream().collect(Collectors.groupingBy(Danger::getFullName));
        Map<String, List<Danger>> localFullIdMap = local.stream().collect(Collectors.groupingBy(Danger::getFullId));

        for (int i = 0; i < data.size(); i++) {
            JSONObject jsonObject1 = (JSONObject) data.get(i);
            String fullName = (String) jsonObject1.get("fullName");
            String fullId = (String) jsonObject1.get("fullId");
            List<Danger> list = localFullIdMap.get(fullId);
            if (ObjectUtils.isEmpty(list)) {
                // 同步新增
                if (add != null && add.equals(1)) {
                    if (ObjectUtils.isNotEmpty(localFullNameMap.get(fullName))) {
                        log.info("如果本地有存在的 同名称的隐患 则忽略 不新增");
                        continue;
                    }
                    Danger newDanger = new Danger();
                    newDanger.setLevel((Integer) jsonObject1.get("level"));
                    newDanger.setChangeLimit((Integer) jsonObject1.get("changeLimit"));
                    newDanger.setRecordStatus((Integer) jsonObject1.get("recordStatus"));
                    newDanger.setContent((String) jsonObject1.get("content"));
                    newDanger.setFullName((String) jsonObject1.get("fullName"));
                    newDanger.setFullId((String) jsonObject1.get("fullId"));
                    Date date = Calendar.getInstance().getTime();
                    newDanger.setLastPushTime(date);
                    newDanger.setCreateTime(date);
                    newDanger.setTenantId(tenantId);

                    newDanger.setDangerTypeId(Long.valueOf(tenant.getProjectId() + jsonObject1.get("dangerTypeId")));
                    newDanger.setDeleteStatus(0);
                    save(newDanger);
                }
            } else {
                // 同步覆盖
                if (cover != null && cover.equals(1)) {
                    //根据fullId 设置
                    Danger e0 = list.get(0);
                    if (e0.getLevel().equals(jsonObject1.get("level")) && e0.getChangeLimit().equals(jsonObject1.get("changeLimit"))
                            && e0.getFullName().equals(jsonObject1.get("fullName")) && e0.getRecordStatus().equals(jsonObject1.get("recordStatus"))) {
                        log.info("隐患信息相同，不需要同步");
                        continue;
                    }
                    e0.setLevel((Integer) jsonObject1.get("level"));
                    e0.setChangeLimit((Integer) jsonObject1.get("changeLimit"));
                    e0.setRecordStatus((Integer) jsonObject1.get("recordStatus"));
                    e0.setContent((String) jsonObject1.get("content"));
                    e0.setFullName((String) jsonObject1.get("fullName"));
                    e0.setLastPushTime(Calendar.getInstance().getTime());

                    UpdateWrapper<Danger> updateWrapper = new UpdateWrapper();
                    updateWrapper.eq("tenant_id", tenantId);
                    updateWrapper.eq("full_id", fullId);
                    getBaseMapper().update(e0, updateWrapper);

                }
            }
        }
    }
}

